using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using PickGold.Charting;

namespace PickGold.Charting.ChartTypes
{
	internal class ColumnChart : PointChart
	{
		private string _shiftedSerName;
		private double _shiftedX;
		protected COPCoordinates coordinates;
		protected bool drawSeriesSideBySide;
		protected bool useTwoValues;

		public ColumnChart()
			: base(false)
		{
			this._shiftedSerName = "";
			this.drawSeriesSideBySide = true;
			this.coordinates = COPCoordinates.X;
		}

		protected virtual void DrawColumn2D(ChartGraphics graph, Axis vAxis, RectangleF rectSize, DataPoint point, Series ser)
		{
			graph.FillRectangleRel(rectSize, point.Color, point.BackHatchStyle, point.BackImage, point.BackImageWrapMode, point.BackImageTransparentColor, point.BackImageAlignment, point.BackGradientStyle, point.BackSecondaryColor, point.BorderColor, point.BorderWidth, point.BorderDashStyle, ser.ShadowColor, ser.ShadowOffset, PenAlignment.Inset, ChartGraphics.GetBarDrawingStyle(point), true);
		}

		protected virtual void DrawLabel(ChartArea area, ChartGraphics graph, CommonElements common, RectangleF columnPosition, DataPoint point, Series ser, int pointIndex)
		{
		}

		protected override LabelAlignmentStyles GetAutoLabelPosition(Series series, int pointIndex)
		{
			if (series.Points[pointIndex].YValues[0] >= 0.0)
			{
				return LabelAlignmentStyles.Top;
			}
			return LabelAlignmentStyles.Bottom;
		}

		public override Image GetImage(ChartTypeRegistry registry)
		{
			return (Image)registry.ResourceManager.GetObject(this.Name + "ChartType");
		}

		public override LegendImageStyle GetLegendImageStyle(Series series)
		{
			return LegendImageStyle.Rectangle;
		}

		public override void Paint(ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
		{
			base.Common = common;
			this.ProcessChartType(false, false, graph, common, area, seriesToDraw);
			this.ProcessChartType(true, false, graph, common, area, seriesToDraw);
		}

		private void ProcessChartType(bool labels, bool selection, ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
		{
			if (area.Area3DStyle.Enable3D)
			{
				this.ProcessChartType3D(labels, selection, graph, common, area, seriesToDraw);
			}
			else
			{
				SizeF relativeSize = graph.GetRelativeSize(new SizeF(1.1f, 1.1f));
				List<string> seriesFromChartType = area.GetSeriesFromChartType(this.Name);
				bool drawSeriesSideBySide = this.drawSeriesSideBySide;
				foreach (string str in seriesFromChartType)
				{
					if (common.DataManager.Series[str].IsCustomPropertySet("DrawSideBySide"))
					{
						string strA = common.DataManager.Series[str]["DrawSideBySide"];
						if (string.Compare(strA, "False", StringComparison.OrdinalIgnoreCase) == 0)
						{
							drawSeriesSideBySide = false;
						}
						else
						{
							if (string.Compare(strA, "True", StringComparison.OrdinalIgnoreCase) == 0)
							{
								drawSeriesSideBySide = true;
								continue;
							}
							if (string.Compare(strA, "Auto", StringComparison.OrdinalIgnoreCase) != 0)
							{
								throw new InvalidOperationException(SR.ExceptionAttributeDrawSideBySideInvalid);
							}
						}
					}
				}
				double count = seriesFromChartType.Count;
				if (!drawSeriesSideBySide)
				{
					count = 1.0;
				}
				bool flag2 = ChartHelper.IndexedSeries(base.Common, area.GetSeriesFromChartType(this.Name).ToArray());
				int num2 = 0;
				foreach (Series series in common.DataManager.Series)
				{
					if (((string.Compare(series.ChartTypeName, this.Name, true, CultureInfo.CurrentCulture) != 0) || (series.ChartArea != area.Name)) || ((series.Points.Count == 0) || !series.IsVisible()))
					{
						continue;
					}
					this.ShiftedSerName = series.Name;
					Axis vAxis = area.GetAxis(AxisName.Y, series.YAxisType, series.YSubAxisName);
					Axis axis = area.GetAxis(AxisName.X, series.XAxisType, series.XSubAxisName);
					double viewMaximum = axis.ViewMaximum;
					double viewMinimum = axis.ViewMinimum;
					double num5 = vAxis.ViewMaximum;
					double num6 = vAxis.ViewMinimum;
					double position = vAxis.GetPosition(vAxis.Crossing);
					bool sameInterval = false;
					double interval = 1.0;
					if (!flag2)
					{
						if ((series.Points.Count == 1) && (((series.XValueType == ChartValueType.Date) || (series.XValueType == ChartValueType.DateTime)) || ((series.XValueType == ChartValueType.Time) || (series.XValueType == ChartValueType.DateTimeOffset))))
						{
							area.GetPointsInterval(seriesFromChartType, axis.IsLogarithmic, axis.logarithmBase, true, out sameInterval);
							if (!double.IsNaN(axis.majorGrid.GetInterval()) && (axis.majorGrid.GetIntervalType() != DateTimeIntervalType.NotSet))
							{
								interval = ChartHelper.GetIntervalSize(axis.minimum, axis.majorGrid.GetInterval(), axis.majorGrid.GetIntervalType());
							}
							else
							{
								interval = ChartHelper.GetIntervalSize(axis.minimum, axis.Interval, axis.IntervalType);
							}
						}
						else
						{
							interval = area.GetPointsInterval(seriesFromChartType, axis.IsLogarithmic, axis.logarithmBase, true, out sameInterval);
						}
					}
					double num9 = series.GetPointWidth(graph, axis, interval, 0.8) / count;
					if (!selection)
					{
						common.Chart.CallOnPrePaint(new ChartPaintEventArgs(series, graph, common, area.PlotAreaPosition));
					}
					int pointIndex = 0;
					foreach (DataPoint point in series.Points)
					{
						double num15;
						double num16;
						double logValue = vAxis.GetLogValue(this.GetYValue(common, area, series, point, pointIndex, this.useTwoValues ? 1 : 0));
						if (logValue > num5)
						{
							logValue = num5;
						}
						if (logValue < num6)
						{
							logValue = num6;
						}
						double linearPosition = vAxis.GetLinearPosition(logValue);
						double num13 = 0.0;
						if (this.useTwoValues)
						{
							double axisValue = vAxis.GetLogValue(this.GetYValue(common, area, series, point, pointIndex, 0));
							if (axisValue > num5)
							{
								axisValue = num5;
							}
							else if (axisValue < num6)
							{
								axisValue = num6;
							}
							num13 = vAxis.GetLinearPosition(axisValue);
						}
						else
						{
							num13 = position;
						}
						pointIndex++;
						if (flag2)
						{
							num16 = ((axis.GetPosition((double)pointIndex) - ((num9 * count) / 2.0)) + (num9 / 2.0)) + (num2 * num9);
							num15 = axis.GetPosition((double)pointIndex);
						}
						else if (sameInterval)
						{
							num16 = ((axis.GetPosition(point.XValue) - ((num9 * count) / 2.0)) + (num9 / 2.0)) + (num2 * num9);
							num15 = axis.GetPosition(point.XValue);
						}
						else
						{
							num16 = axis.GetPosition(point.XValue);
							num15 = axis.GetPosition(point.XValue);
						}
						this.ShiftedX = num16 - num15;
						if ((linearPosition < num13) && ((num13 - linearPosition) < relativeSize.Height))
						{
							linearPosition = num13 - relativeSize.Height;
						}
						if ((linearPosition > num13) && ((linearPosition - num13) < relativeSize.Height))
						{
							linearPosition = num13 + relativeSize.Height;
						}
						RectangleF empty = RectangleF.Empty;
						try
						{
							empty.X = (float)(num16 - (num9 / 2.0));
							empty.Width = (float)num9;
							if (num13 < linearPosition)
							{
								empty.Y = (float)num13;
								empty.Height = ((float)linearPosition) - empty.Y;
							}
							else
							{
								empty.Y = (float)linearPosition;
								empty.Height = ((float)num13) - empty.Y;
							}
						}
						catch (OverflowException)
						{
							continue;
						}
						if (!point.IsEmpty)
						{
							if (common.ProcessModePaint)
							{
								if (!labels)
								{
									double yValue = flag2 ? ((double)pointIndex) : point.XValue;
									yValue = axis.GetLogValue(yValue);
									if ((yValue < viewMinimum) || (yValue > viewMaximum))
									{
										continue;
									}
									bool flag4 = false;
									if ((empty.X < area.PlotAreaPosition.X) || (empty.Right > area.PlotAreaPosition.Right))
									{
										graph.SetClip(area.PlotAreaPosition.ToRectangleF());
										flag4 = true;
									}
									graph.StartHotRegion(point);
									this.DrawColumn2D(graph, vAxis, empty, point, series);
									graph.EndHotRegion();
									if (flag4)
									{
										graph.ResetClip();
									}
								}
								else if (this.useTwoValues)
								{
									this.DrawLabel(area, graph, common, empty, point, series, pointIndex);
								}
							}
							if (common.ProcessModeRegions && !labels)
							{
								common.HotRegionsList.AddHotRegion(empty, point, series.Name, pointIndex - 1);
							}
						}
					}
					if (!selection)
					{
						common.Chart.CallOnPostPaint(new ChartPaintEventArgs(series, graph, common, area.PlotAreaPosition));
					}
					if (drawSeriesSideBySide)
					{
						num2++;
					}
					if (labels && !this.useTwoValues)
					{
						base.ProcessChartType(false, graph, common, area, seriesToDraw);
					}
				}
			}
		}

		private void ProcessChartType3D(bool labels, bool selection, ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
		{
			if (!labels || selection)
			{
				SizeF relativeSize = graph.GetRelativeSize(new SizeF(1.1f, 1.1f));
				List<string> seriesNamesList = null;
				bool drawSeriesSideBySide = this.drawSeriesSideBySide;
				if ((!area.Area3DStyle.IsClustered || !this.SideBySideSeries) && !this.Stacked)
				{
					seriesNamesList = new List<string>();
					seriesNamesList.Add(seriesToDraw.Name);
				}
				else
				{
					seriesNamesList = area.GetSeriesFromChartType(this.Name);
					foreach (string str in seriesNamesList)
					{
						if (common.DataManager.Series[str].IsCustomPropertySet("DrawSideBySide"))
						{
							string strA = common.DataManager.Series[str]["DrawSideBySide"];
							if (string.Compare(strA, "False", StringComparison.OrdinalIgnoreCase) == 0)
							{
								drawSeriesSideBySide = false;
							}
							else
							{
								if (string.Compare(strA, "True", StringComparison.OrdinalIgnoreCase) == 0)
								{
									drawSeriesSideBySide = true;
									continue;
								}
								if (string.Compare(strA, "Auto", StringComparison.OrdinalIgnoreCase) != 0)
								{
									throw new InvalidOperationException(SR.ExceptionAttributeDrawSideBySideInvalid);
								}
							}
						}
					}
				}
				foreach (object obj2 in area.GetDataPointDrawingOrder(seriesNamesList, this, selection, this.coordinates, null, base.YValueIndex, drawSeriesSideBySide))
				{
					DataPoint3D pointEx = (DataPoint3D)obj2;
					DataPoint dataPoint = pointEx.dataPoint;
					Series series = dataPoint.series;
					BarDrawingStyle barDrawingStyle = ChartGraphics.GetBarDrawingStyle(dataPoint);
					Axis axis = area.GetAxis(AxisName.Y, series.YAxisType, series.YSubAxisName);
					Axis axis2 = area.GetAxis(AxisName.X, series.XAxisType, series.XSubAxisName);
					float topRightDarkening = 0f;
					float bottomLeftDarkening = 0f;
					double yValue = this.GetYValue(common, area, series, pointEx.dataPoint, pointEx.index - 1, this.useTwoValues ? 1 : 0);
					yValue = axis.GetLogValue(yValue);
					if (yValue > axis.ViewMaximum)
					{
						topRightDarkening = 0.5f;
						yValue = axis.ViewMaximum;
					}
					if (yValue < axis.ViewMinimum)
					{
						topRightDarkening = 0.5f;
						yValue = axis.ViewMinimum;
					}
					double linearPosition = axis.GetLinearPosition(yValue);
					double position = 0.0;
					if (this.useTwoValues)
					{
						double axisValue = axis.GetLogValue(this.GetYValue(common, area, series, dataPoint, pointEx.index - 1, 0));
						if (axisValue > axis.ViewMaximum)
						{
							bottomLeftDarkening = 0.5f;
							axisValue = axis.ViewMaximum;
						}
						else if (axisValue < axis.ViewMinimum)
						{
							bottomLeftDarkening = 0.5f;
							axisValue = axis.ViewMinimum;
						}
						position = axis.GetLinearPosition(axisValue);
					}
					else
					{
						position = axis.GetPosition(axis.Crossing);
					}
					if (!drawSeriesSideBySide)
					{
						pointEx.xPosition = pointEx.xCenterVal;
					}
					this.ShiftedX = pointEx.xPosition - pointEx.xCenterVal;
					if ((linearPosition < position) && ((position - linearPosition) < relativeSize.Height))
					{
						linearPosition = position - relativeSize.Height;
					}
					if ((linearPosition > position) && ((linearPosition - position) < relativeSize.Height))
					{
						linearPosition = position + relativeSize.Height;
					}
					RectangleF empty = RectangleF.Empty;
					try
					{
						empty.X = (float)(pointEx.xPosition - (pointEx.width / 2.0));
						empty.Width = (float)pointEx.width;
						if (position < linearPosition)
						{
							float num7 = bottomLeftDarkening;
							bottomLeftDarkening = topRightDarkening;
							topRightDarkening = num7;
							empty.Y = (float)position;
							empty.Height = ((float)linearPosition) - empty.Y;
						}
						else
						{
							empty.Y = (float)linearPosition;
							empty.Height = ((float)position) - empty.Y;
						}
					}
					catch (OverflowException)
					{
						continue;
					}
					GraphicsPath path = null;
					double logValue = pointEx.indexedSeries ? ((double)pointEx.index) : dataPoint.XValue;
					logValue = axis2.GetLogValue(logValue);
					if ((logValue >= axis2.ViewMinimum) && (logValue <= axis2.ViewMaximum))
					{
						bool flag2 = false;
						if ((empty.Right > area.PlotAreaPosition.X) && (empty.X < area.PlotAreaPosition.Right))
						{
							if (empty.X < area.PlotAreaPosition.X)
							{
								empty.Width -= area.PlotAreaPosition.X - empty.X;
								empty.X = area.PlotAreaPosition.X;
							}
							if (empty.Right > area.PlotAreaPosition.Right)
							{
								empty.Width -= empty.Right - area.PlotAreaPosition.Right;
							}
							if (empty.Width < 0f)
							{
								empty.Width = 0f;
							}
							DrawingOperationTypes drawElement = DrawingOperationTypes.DrawElement;
							if (common.ProcessModeRegions)
							{
								drawElement |= DrawingOperationTypes.CalcElementPath;
							}
							if ((!dataPoint.IsEmpty && (empty.Height > 0f)) && (empty.Width > 0f))
							{
								graph.StartHotRegion(dataPoint);
								path = graph.Fill3DRectangle(empty, pointEx.zPosition, pointEx.depth, area.matrix3D, area.Area3DStyle.LightStyle, dataPoint.Color, topRightDarkening, bottomLeftDarkening, dataPoint.BorderColor, dataPoint.BorderWidth, dataPoint.BorderDashStyle, barDrawingStyle, true, drawElement);
								graph.EndHotRegion();
								if (common.ProcessModeRegions && !labels)
								{
									common.HotRegionsList.AddHotRegion(path, false, graph, dataPoint, series.Name, pointEx.index - 1);
								}
								if (path != null)
								{
									path.Dispose();
								}
							}
							if (flag2)
							{
								graph.ResetClip();
							}
							this.ProcessSinglePoint3D(pointEx, selection, graph, common, area, empty, pointEx.index - 1);
						}
					}
				}
				base.DrawAccumulated3DLabels(graph, common, area);
			}
		}

		protected virtual void ProcessSinglePoint3D(DataPoint3D pointEx, bool selection, ChartGraphics graph, CommonElements common, ChartArea area, RectangleF columnPosition, int pointIndex)
		{
			base.ProcessSinglePoint3D(pointEx, graph, common, area);
		}

		protected override bool ShouldDrawMarkerOnViewEdgeX()
		{
			return false;
		}

		public override bool ApplyPaletteColorsToPoints
		{
			get
			{
				return false;
			}
		}

		public override bool DataPointsInLegend
		{
			get
			{
				return false;
			}
		}

		public override bool ExtraYValuesConnectedToYAxis
		{
			get
			{
				return false;
			}
		}

		public override string Name
		{
			get
			{
				return "Column";
			}
		}

		public override bool RequireAxes
		{
			get
			{
				return true;
			}
		}

		public override string ShiftedSerName
		{
			get
			{
				return this._shiftedSerName;
			}
			set
			{
				this._shiftedSerName = value;
			}
		}

		public override double ShiftedX
		{
			get
			{
				return this._shiftedX;
			}
			set
			{
				this._shiftedX = value;
			}
		}

		public override bool SideBySideSeries
		{
			get
			{
				return true;
			}
		}

		public override bool Stacked
		{
			get
			{
				return false;
			}
		}

		public override bool SupportLogarithmicAxes
		{
			get
			{
				return true;
			}
		}

		public override bool SwitchValueAxes
		{
			get
			{
				return false;
			}
		}

		public override int YValuesPerPoint
		{
			get
			{
				return 1;
			}
		}

		public override bool ZeroCrossing
		{
			get
			{
				return true;
			}
		}
	}
}

